package model.domain;

import java.util.ArrayList;
import java.util.HashMap;

import model.algorithm.Action;
import model.algorithm.SearchDomain;
import model.algorithm.State;

public class Puzzle8Domain implements SearchDomain {			//Puzzle8Domain is sort of a SearchDomain and implements its interface

	Puzzle8DomainState start,goal;
	
	public Puzzle8Domain (String start){
				this.start = new Puzzle8DomainState(start);			// sets the startState to be the given state
				this.goal = new Puzzle8DomainState(null);			// declaring the goal state
				this.goal.setState("123456780");					// This specific game is 8Puzzle so the final solution will always will be that string				
	}
    
	@Override
	public State getStartState() {
		return start;
	}

	@Override
	public State getGoalState() {
		return goal;
	}

	@Override
	public HashMap<Action, State> getAllPossibleMoves(State currentState) {			// getAllPossibleMoves override
		HashMap<Action, State> moves = new HashMap<Action, State>();				//  finds the index of the '0' char -
		int index = whereZero(currentState);										// and according to its position, adds to an Integer ArrayList
		ArrayList<Integer> tmpArray = new ArrayList<Integer>();						// the possible locations for switches
		switch (index){
		case 0: {tmpArray.add(1);
				tmpArray.add(3);
				break;}
		case 1: {tmpArray.add(0);
				tmpArray.add(2);
				tmpArray.add(4);
				break;}
		case 2: {tmpArray.add(1);
				tmpArray.add(5);
				break;}
		case 3: {tmpArray.add(0);
				tmpArray.add(4);
				tmpArray.add(6);
				break;}
		case 4: {tmpArray.add(1);
				tmpArray.add(3);
				tmpArray.add(5);
				tmpArray.add(7);
				break;}
		case 5:	{tmpArray.add(2);
				tmpArray.add(4);
				tmpArray.add(8);
				break;}
		case 6: {tmpArray.add(3);
				tmpArray.add(7);
				break;}
		case 7: {tmpArray.add(4);
				tmpArray.add(6);
				tmpArray.add(8);
				break;}
		case 8: {tmpArray.add(5);
				tmpArray.add(7);
				break;}				
		}
		
		char[] tmpCharArray;
		String tmpAction;
		for (int i=0; i<tmpArray.size(); i++){
			tmpCharArray = currentState.getState().toCharArray();			// gets the current state's describing String as Char array
			
			switchChars(tmpCharArray, index, tmpArray.get(i));				// Switches in the char array between the '0' and the option from the arraylist created before
			tmpAction = ("Switch 0 with " + currentState.getState().toCharArray()[tmpArray.get(i)]);		// describes in string the action that was made
			String stateString = new String(tmpCharArray);
			moves.put(new Action(tmpAction) , new Puzzle8DomainState(stateString));		//the HMap moves gets the describing string and the possible state
																						// done for each and every option that was added to the array list
		}
		/*for (Action key: moves.keySet()){								// internal printing check  -- don't forget to delete!
			System.out.println(moves.get(key));
		}*/

		return moves;
		
	}

	private int whereZero (State currentState){
		char [] chars = currentState.getState().toCharArray(); 			// copying the state describing string into a char array (convenient)
		for (int i=0; i<=8; i++)								// 8(+1) is the size of the matrix and it will always be true for this game!
			if (chars[i] == '0')
				return i;									// The only possible case for an error here is bad initial state
		return 0;
	}
	
	// switch two chars in array
	private void switchChars(char[] tmpString,int i, Integer j){
		char tmp=tmpString[i];
		tmpString[i]=tmpString[j];
		tmpString[j]=tmp;
	}
	
	public String returnTheProblem(){
		return "maze" + getStartState().getState();
	}
}
